﻿using DotNetOpenAuth.AspNet;
using Inovout.Account.Web.Filters;
using Inovout.Account.Web.Models;
using Inovout.Account.Web.OpenIdClients;
using Inovout.EntityPropertyValidation;
using Inovout.Memberships;
using Inovout.Memberships.Models;
using Inovout.Memberships.Services;
using Inovout.People.Memberships.Models;
using Inovout.People.Memberships.Services;
using Inovout.People.Models;
using Inovout.RedictUrls;
using Inovout.Runtime;
using Inovout.Security;
using Inovout.Security.Models;
using Inovout.Security.Services;
using Inovout.Services;
using Inovout.Web.Mvc;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;

namespace Inovout.Account.Web.Controllers
{
    [AllowAnonymous]
    public class PersonController : BaseController
    {
        private IFormsAuthenticationService authenticateService;
        private IPersonMembershipService personMembershipService;
        private IMembershipUserService membershipUserService;

        public PersonController(IFormsAuthenticationService authenticateService,
            IPersonMembershipService personMembershipService, IMembershipUserService membershipUserService)
        {
            this.personMembershipService = personMembershipService;
            this.authenticateService = authenticateService;
            this.membershipUserService = membershipUserService;

        }

        public ActionResult Bind(string returnUrl, int? id,string provider,string providerUserId)
        {
            PersonSignUpInfo personSignUpInfo = new PersonSignUpInfo();
            if (id.HasValue)
            {

                personSignUpInfo.MembershipId = id;
                var membershipUser = (MembershipUser)membershipUserService.FindById(id.GetValueOrDefault());
                personSignUpInfo.OpenIdClaimedIdentifier = membershipUser.SystemUser.Name;
                var membership = (Inovout.Memberships.Models.Membership)membershipUser.Membership;
                IRepositoryService<PersonMembership> personMembershipService = ComponentRegistry.Resolve<IRepositoryService<PersonMembership>>();
                PersonMembership personMembership = personMembershipService.FindById(membership.Id);
                personSignUpInfo.PersonEmail = personMembership.Person.Email;
                personSignUpInfo.PersonName = personMembership.Person.Name;
                personSignUpInfo.PersonMobile = personMembership.Person.Mobile;
                personSignUpInfo.OpenIdProvider = provider;
                personSignUpInfo.OpenIdClaimedIdentifier = providerUserId;
                personSignUpInfo.IsExtensional = true;
            }
            return View("SignUp", personSignUpInfo);
        }

        protected ActionResult SignInSuccess(IMembershipUser membershipUser, bool rememberMe, string returnUrl)
        {
            FormsAuthentication.SetAuthCookie(membershipUser.Name, rememberMe);
            if (!string.IsNullOrEmpty(returnUrl))
            {
                return Redirect(returnUrl);
            }
            else
            {
                return Redirect("~/");
            }
        }

        //protected ActionResult AutoSignIn(string email, string returnUrl)
        //{
        //    MembershipUserService membershipUserServiceService = Inovout.ComponentRegistry.Resolve<MembershipUserService>();
        //    //Inovout.Memberships.IMembershipUser membershipUser = membershipUserServiceService.FindByUserName(email);
        //    Inovout.Memberships.IMembershipUser membershipUser = membershipUserServiceService.FindByEmail(email);
        //    return SignInSuccess(membershipUser, false, returnUrl);
        //}

        public ActionResult Edit(string returnUrl)
        {
            Inovout.Memberships.Models.Membership membership = base.Membership as Memberships.Models.Membership;
            IRepositoryService<PersonMembership> personService = ComponentRegistry.Resolve<IRepositoryService<PersonMembership>>();
            PersonMembership personMembership = personService.FindById(membership.Id);

            string emailPropertyName = "Email";
            string type = membership.MembershipType.ToString();
            EntityPropertyValidationResult emailValidationResult = Inovout.ComponentRegistry.Resolve<IEntityPropertyValidationResultService>().FindByEntiry(membership, type, emailPropertyName);
            if (emailValidationResult != null)
            {
                ViewBag.IsEmailValid = emailValidationResult.IsValid;
            }
            string mobilePropertyName = "Mobile";
            EntityPropertyValidationResult mobileValidationResult = Inovout.ComponentRegistry.Resolve<IEntityPropertyValidationResultService>().FindByEntiry(membership, type, mobilePropertyName);
            if (mobileValidationResult != null)
            {
                ViewBag.IsMobileValid = mobileValidationResult.IsValid;
            }

            return View(personMembership);
        }

        [HttpPost]
        public ActionResult Save(PersonMembership model, bool isEmailValid, string returnUrl)
        {
            ViewBag.IsEmailValid = isEmailValid;
            if (ModelState.IsValid)
            {
                IRepositoryService<PersonMembership> personMembershipService = ComponentRegistry.Resolve<IRepositoryService<PersonMembership>>();
                IRepositoryService<Person> personService = ComponentRegistry.Resolve<IRepositoryService<Person>>();
                model.Person.Mobile = model.Mobile;
                model.Person.Name = model.Name;

                personMembershipService.Save(model);

                return RedirectToAction("Message", new { messageType = MessageType.Success, message = Url.Encode("保存成功 <a href='" + returnUrl + "'>继续</a>") });
            }
            return View("Edit", model);
        }

        public ActionResult SignUp(string returnUrl)
        {
            ViewBag.ReturnUrl = returnUrl;
            return View();
        }

        [HttpPost]
        //[ValidateAntiForgeryToken]
        public ActionResult SignUp(PersonSignUpInfo model, string returnUrl)
        {
            ValidateIsFormsUserOrNot(model);
            if (ModelState.IsValid)
            {
                MembershipUser memberUser = new MembershipUser();
                if (model.MembershipId.HasValue)
                {
                    memberUser = (MembershipUser)membershipUserService.FindById(model.MembershipId.GetValueOrDefault());
                }
                else
                {
                    memberUser = (MembershipUser)membershipUserService.FindByByUserNameOrEmailForLocal(model.UserName,model.PersonEmail);
                }
                if (memberUser == null)
                {
                    //注册逻辑，并注意跳转至首页，建议跳转至注册成功页面。
                    MembershipUser membershipUser = (MembershipUser)personMembershipService.Create(model.Person, model.FormsUserCredential, MembershipUserStatus.Inactivate);
                    //根据邮箱地址，保存验证表信息（未激活）
                    var membership = (Inovout.Memberships.Models.Membership)membershipUser.Membership;
                    CreateValidationResult(membership.Id);
                    //保存RedirctUrl表信息
                    RedirctUrl entity = CreateRedirctUrl(model.PersonEmail, membershipUser.Id, returnUrl);
                    //发送邮件验证
                    string result = SendEmail(model.PersonEmail, entity.ActionUrl);
                    if (!string.IsNullOrEmpty(result))
                    {//如果该邮箱地址是不可用的，显示错误消息
                        ModelState.AddModelError("PersonEmail", result);
                    }
                    else
                    {
                        return RedirectToAction("Activate", "MembershipUser", new { email = model.PersonEmail, membershipUser = membershipUser.Id, returnUrl = returnUrl });
                    }
                }
                else if (memberUser.Status == MembershipUserStatus.Initial)
                {
                    //update status as InActivate
                    UserCredentialService userCredentialService = new Security.Services.UserCredentialService();
                
                    var userCredential = userCredentialService.FindUserCredentialByProviderIdentifier(model.OpenIdProvider, model.OpenIdClaimedIdentifier);
                    userCredential.Email = model.PersonEmail;
                    Inovout.ComponentRegistry.Resolve<IRepositoryService<UserCredential>>().Save(userCredential);
                    memberUser.Status = MembershipUserStatus.Inactivate;
                    memberUser.Email = model.PersonEmail;
                    Inovout.ComponentRegistry.Resolve<IRepositoryService<MembershipUser>>().Save(memberUser);
                    var membership = (Inovout.Memberships.Models.Membership)memberUser.Membership;
                    IRepositoryService<PersonMembership> personMembershipService = ComponentRegistry.Resolve<IRepositoryService<PersonMembership>>();
                    PersonMembership personMembership = personMembershipService.FindById(membership.Id);
                    // personMembership.Person = model.Person;
                    personMembership.Person.Email = model.PersonEmail;
                    personMembership.Person.Name = model.PersonName;
                    personMembership.Person.Mobile = model.PersonMobile;
                    personMembershipService.Save(personMembership);
                    CreateValidationResult(membership.Id);
                    RedirctUrl entity = CreateRedirctUrl(model.PersonEmail, memberUser.Id, returnUrl);
                    string result = SendEmail(model.PersonEmail, entity.ActionUrl);
                    if (!string.IsNullOrEmpty(result))
                    {//如果该邮箱地址是不可用的，显示错误消息
                        ModelState.AddModelError("PersonEmail", result);
                    }
                    else
                    {
                        return RedirectToAction("Activate", "MembershipUser", new { email = model.PersonEmail, membershipUser = memberUser.Id, returnUrl = returnUrl });
                    }

                }
                else
                {
                    ModelState.AddModelError("PersonEmail", "该邮箱已存在");
                    ModelState.AddModelError("UserName", "该邮箱已存在");
                    return View(model);
                }

            }
            // 如果我们进行到这一步时某个地方出错，则重新显示表单
            return View(model);
        }

        private static void CreateValidationResult(int id)
        {
            Inovout.Memberships.Models.Membership membership = Inovout.ComponentRegistry.Resolve<MembershipService>().FindById(id);
            EntityPropertyValidationResult validationResult = new EntityPropertyValidationResult();
            validationResult.EntityType = membership.MembershipType.ToString();
            validationResult.EntityId = membership.Id.ToString();
            validationResult.IsValid = false;
            ComponentRegistry.Resolve<IEntityPropertyValidationResultService>().SaveValidationResult(validationResult, "Email");
        }

        private void ValidateIsFormsUserOrNot(PersonSignUpInfo model)
        {
            if (model.IsExtensional)
            {
                ModelState.Remove("UserName");
                ModelState.Remove("Password");
                ModelState.Remove("ConfirmPassword");
            }
            else
            {
                ModelState.Remove("OpenIdClaimedIdentifier");
                ModelState.Remove("OpenIdProvider");
                ModelState.Remove("OpenIdUserName");
            }
        }

        private RedirctUrl CreateRedirctUrl(string email, int id, string returnUrl)
        {
            RedirctUrl entity = new RedirctUrl();
            entity.OrginalUrl = (new Uri(this.Request.Url, Url.Action("ActivateUser", "MembershipUser", new { Email = email, MembershipUser = id, ReturnUrl = returnUrl }))).AbsoluteUri;
            entity.FailedUrl = (new Uri(this.Request.Url, Url.Action("ActivateFailed", "MembershipUser", new { Email = email }))).AbsoluteUri;
            string guid = Guid.NewGuid().ToString("N");
            entity.ActionUrl = (new Uri(this.Request.Url, Url.Action("Index", "Go", new { key = guid }))).AbsoluteUri;
            Inovout.ComponentRegistry.Resolve<IRedictUrlService>().Save(entity);
            return entity;
        }

        private string SendEmail(string email, string actionUrl)
        {
            ViewBag.Email = email;

            string subject = "3Cloud 新用户激活邮件";
            string plate = @"亲爱的$(email)："
                + Environment.NewLine
                + Environment.NewLine + "感谢您申请注册三宝云！请点击链接激活账户："
                + Environment.NewLine + "$(url)"
                + Environment.NewLine
                + Environment.NewLine + "如果上述链接点击无效，请将该网页地址复制到浏览器地址栏中打开。"
                + Environment.NewLine
                + Environment.NewLine + "如果您没有申请注册三宝云，请忽略此邮件。"
                + Environment.NewLine
                + Environment.NewLine + "---------------------------------------------------------------------------------------------------------"
                + Environment.NewLine
                + Environment.NewLine + "本邮件由系统自动发出，请勿回复。";

            Dictionary<string, string> contents = new Dictionary<string, string>();
            contents.Add("email", email);
            contents.Add("url", actionUrl);
            string result = Inovout.ComponentRegistry.Resolve<IRedictUrlService>().SendMail(plate, contents, subject);
            return result;
        }
    }
}